﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using HtmlAgilityPack;

namespace DotNet.Common.Kit
{
    public class HtmlDocHelper
    {
        LogerHelper logger = new LogerHelper(DirType.Local, MessageType.Exception);
        string _headHtml="";  //input
        string _footHtml="";  //input

        string _htmlStr = ""; //input 传入HTML字符串文档
        HtmlAgilityPack.HtmlDocument _htmlDoc = new HtmlAgilityPack.HtmlDocument();
        private static readonly char[] trimChars = { ' ', '\r', '\n' };//分隔字符    
        /// <summary>
        /// 传入HTML字符串文档,将其转化为HTMLDocument 以便于处理节点值.
        /// </summary>
        /// <param name="htmlStr"></param>
        public HtmlDocHelper(string htmlStr)
        {
            this._htmlStr = htmlStr;
            _htmlDoc.LoadHtml(_htmlStr);
        }
        public string HtmlStr
        {
            get { return this._htmlStr; }
            set {
                _htmlStr = value;
                _htmlDoc.Load(_htmlStr);
            }
        }

        public HtmlDocHelper(string headFile, string footFile)
        {
            StreamReader srHead = new StreamReader(headFile,System.Text.Encoding.Default);
            _headHtml=srHead.ReadToEnd();
            srHead.Close();

            StreamReader srFoot = new StreamReader(footFile,System.Text.Encoding.Default);
            _footHtml = srFoot.ReadToEnd();
            srFoot.Close();
        }

        public string HeadHtml
        {
            get { return _headHtml; }
        }

        public string FootHtml
        {
            get { return _footHtml;}
        }
        public string GetHtmlDoc(string content)
        {
            return _headHtml +"\r\n"+ content + _footHtml;
        }
        public string CreateImgDom(string src,string id,string alt,string style)
        {
            string img="<img id='"+id+"' src='"+src+"' alt='"+alt+"' style='"+style+"' />";
            return img+"\r\n";
        }

        public bool SetBodyContent(System.Windows.Forms.HtmlDocument htmlDoc, string bodyConten)
        {
            htmlDoc.Body.InnerHtml = bodyConten;
            return false;
        }
        /// <summary>
        /// 得到Title值
        /// </summary>
        /// <param name="htmlStr"></param>
        /// <returns>不包含title则返回 ""</returns>
        public string GetHtmlTitle()
        {
            string retTitle = "";
            HtmlNodeCollection hncTitle=this._htmlDoc.DocumentNode.SelectNodes("//title");
            if (hncTitle != null) //title标签存在.
            {
                retTitle = hncTitle[0].InnerText.Trim(trimChars);
            }
            return retTitle;
        }

        public string GetHtmlBody()
        {
            string retBody = "";
            HtmlNodeCollection hncTitle = this._htmlDoc.DocumentNode.SelectNodes("//body");
            if (hncTitle != null) //title标签存在.
            {
                retBody = hncTitle[0].InnerText.Trim(trimChars);
            }
            return retBody;
        }
        /// <summary>
        /// 得到单个节点的值
        /// </summary>
        /// <param name="nodePath">路径</param>
        /// <returns>含有XPATH的节点返回InnerText,否则返回""</returns>
        public string GetNode(string nodePath)
        {
            //List<string> retList = new List<string>();
            string retStr= "";
            HtmlNodeCollection hncNode = this._htmlDoc.DocumentNode.SelectNodes(nodePath);
            if (hncNode != null)
            {
                retStr = hncNode[0].InnerText.Trim(trimChars);
            }
            else
            {
                return "";
            }
            return retStr;
        }
        /// <summary>
        /// 得到单个节点的属性值。
        /// </summary>
        /// <param name="nodeXPath">节点的XPATH</param>
        /// <param name="attr">节点的属性</param>
        /// <returns></returns>
        public string GetNodeAttr(string nodeXPath, string attr)
        {
            string retAttrStr = "";
            HtmlNodeCollection hncNode = this._htmlDoc.DocumentNode.SelectNodes(nodeXPath);
            if (hncNode != null)
            {
                retAttrStr = hncNode[0].Attributes[attr].Value.ToString().Trim(trimChars);
            }
            else
            {
                return "";
            }
            return retAttrStr;
        }
        /// <summary>
        /// 对于无法根据特征值唯一确定的节点，用索引号来指定以实际位置为准，索引从1开始
        /// </summary>
        /// <param name="nodeXPath"></param>
        /// <param name="index">节点的位置</param>
        /// <returns></returns>
        public string GetNodeIndex(string nodeXPath, int index)
        {
            string retStr = "";
            HtmlNodeCollection hncNode = this._htmlDoc.DocumentNode.SelectNodes(nodeXPath);
            if (hncNode != null)
            {
                retStr = hncNode[index-1].InnerText.Trim(trimChars);
            }
            else
            {
                return "";
            }
            return retStr;
        }
        /// <summary>
        /// 根据含有的特征串返回值。
        /// </summary>
        /// <param name="nodeXPath"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public string GetNodeKeyWord(string nodeXPath, string key)
        {
            string retStr = "";
            HtmlNodeCollection hncNode = this._htmlDoc.DocumentNode.SelectNodes(nodeXPath);
            if (hncNode != null)
            {
                foreach (HtmlNode node in hncNode)
                {
                    retStr=node.InnerText.Trim(trimChars);
                    if (retStr.Contains(key))
                    {
                        return retStr;
                    }
                }
            }
            return retStr;
        }
        /// <summary>
        /// 得到多个节点的值,相当于一个二维数组.
        /// </summary>
        /// <param name="param">传入的可变参数,确定返回List<string[]>中string的长度可以是类似于xpath:attr这样的串</param>
        /// <returns></returns>
        public List<string[]> GetNodes(params string[] param)
        {
            int len = param.Length;
            List<string[]> list = new List<string[]>();
            string xpath0 = "";
            string attr0 = "";
            HtmlNodeCollection hnc0 = null;// this._htmlDoc.DocumentNode.SelectNodes(param[0]);
            try
            {
                if (param[0].Contains(":"))     //判断第0个节点是否含有attr串.
                {
                    xpath0 = param[0].Split(':')[0];
                    attr0 = param[0].Split(':')[1];
                    hnc0 = this._htmlDoc.DocumentNode.SelectNodes(xpath0);
                }
                else
                {
                    hnc0 = this._htmlDoc.DocumentNode.SelectNodes(param[0]);
                }
                if (hnc0 != null)
                {
                    int index = 0;
                    foreach (HtmlNode node in hnc0)
                    {
                        string[] strList = new string[len];
                        if (attr0 != "")
                            strList[0] = node.Attributes[attr0].Value.ToString().Trim(trimChars);
                        else
                            strList[0] = node.InnerText.Trim(trimChars);
                        for (int i = 1; i < len; i++)
                        {
                            HtmlNodeCollection hnc = null;
                            if (param[i].Contains(":"))
                            {
                                string xpath = param[i].Split(':')[0];
                                string attr = param[i].Split(':')[1];
                                hnc = this._htmlDoc.DocumentNode.SelectNodes(xpath);
                                if (hnc != null)
                                    strList[i] = hnc[index].Attributes[attr].Value.ToString().Trim(trimChars);
                                else
                                    strList[i] = "";
                            }
                            else
                            {
                                hnc = this._htmlDoc.DocumentNode.SelectNodes(param[i]);
                                if (hnc != null)
                                    strList[i] = hnc[index].InnerText.Trim(trimChars);
                                else
                                    strList[i] = "";
                            }
                        }
                        index++;
                        list.Add(strList);
                    }
                }
            }
            catch (Exception ex)
            {
                logger.WriteException(ex);
                return null;
            }
            return list;
        }
    }
}
